/**
 * Witontek.com.
 * Copyright (c) 2012-2017 All Rights Reserved.
 */
package com.witon.witontool.core.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.base.Joiner;
import com.witon.witontool.core.service.DbCheckService;
import com.witon.witontool.core.service.DbCodeService;
import com.witon.witontool.web.controller.dbcheck.model.DbCodeResult;
import com.witon.witontool.web.controller.dbcheck.model.Field;
import com.witon.witontool.web.controller.dbcheck.model.Table;

/**
 * 
 * @author Long
 * @version $Id: DbCodeServiceImpl.java, v 0.1 2017年7月1日 上午8:53:24  xiaolong.ma  Exp $
 */
@Service
public class DbCodeServiceImpl implements DbCodeService {

    private final Logger   logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private DbCheckService dbCheckService;

    /** 
     * @see com.witon.witontool.core.service.DbCodeService#dbCode(long)
     */
    @Override
    public DbCodeResult dbCode(long id, String tableName) {
        logger.info("code {}", id);
        DbCodeResult r = new DbCodeResult();
        List<Table> tableList = getTableList(id);
        r = dbCode(tableList, tableName);
        return r;
    }

    private String convertType(String type) {

        if (type.equals("text") || type.contains("char")) {
            return " String ";
        }

        if (type.contains("time")) {
            return " Date ";
        }
        if (type.equals("int2") || type.equals("int4") || type.equals("int8")
            || type.equals("serial")) {
            return " long ";
        }
        return "";
    }

    private String convertJavaName(String name) {
        //hasy_log  HasyLog
        String s = convertPropertyName(name);
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    private String convertPropertyName(String name) {
        //hasy_log  hasyLog
        if (StringUtils.isBlank(name)) {
            return "";
        }
        String pattern = "_.{1}";
        Pattern r = Pattern.compile(pattern);

        // 现在创建 matcher 对象
        Matcher m = r.matcher(name);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, m.group().substring(1, 2).toUpperCase());
        }
        m.appendTail(sb);
        return sb.toString();
    }

    Table getTable(List<Table> prodList, String name) {
        for (Table t : prodList) {
            if (t.getName().equals(name)) {
                return t;
            }
        }
        return null;
    }

    /** 
     * @see com.witon.witontool.core.service.DbCodeService#getTableList(long)
     */
    @Override
    public List<Table> getTableList(long id) {
        List<Table> tableList = dbCheckService.getTableList(id);
        return tableList;
    }

    /** 
     * @see com.witon.witontool.core.service.DbCodeService#dbCode(java.util.List, java.lang.String)
     */
    @Override
    public DbCodeResult dbCode(List<Table> tableList, String tableName) {
        DbCodeResult r = new DbCodeResult();
        Table table = getTable(tableList, tableName);
        String ModelName = convertJavaName(table.getName());

        r.setModelDoName(ModelName);
        List<String> fieldList = new ArrayList<String>();
        for (Field f : table.getFieldList()) {
            //logger.info("{},{}", f.getType(), convertType(f.getType()));
            String s = "";
            if (StringUtils.isNotBlank(f.getRemarks())) {
                s = "/*   " + f.getRemarks() + "*/  ";
            }
            fieldList.add(s);
            s = "private " + convertType(f.getType()) + " " + convertPropertyName(f.getName())
                + " ;";
            fieldList.add(s);
        }
        r.setModelFieldList(fieldList);

        //dao
        List<String> daoList = new ArrayList<String>();

        daoList.add(ModelName + "Do  getById(long id);");
        daoList.add(" long add(" + ModelName + "Do modelDo);");
        daoList.add(" int deleteById(long id);");
        daoList.add(" int update(" + ModelName + "Do modelDo);");
        r.setDaoList(daoList);

        r.setConvertList(genConvertList(table));

        r.setMapperList(genMapperList(table));
        return r;
    }

    private List<String> genConvertList(Table table) {
        String modelName = convertJavaName(table.getName());
        String doName = modelName + "Do";
        List<String> list = new ArrayList<String>();
        list.add("public static " + doName + " convert(" + modelName + " model) {");
        list.add("if (model == null) {            return null;        }");
        list.add(doName + " ret = new " + doName + "();");
        for (Field f : table.getFieldList()) {
            String fName = convertJavaName(f.getName());
            list.add("ret.set" + fName + "(model.get" + fName + "());");
        }
        list.add("return ret;");
        list.add("}");

        list.add("public static " + modelName + " convert(" + doName + " modelDo) {");
        list.add("if (modelDo == null) {            return null;        }");
        list.add(modelName + " ret = new " + modelName + "();");
        for (Field f : table.getFieldList()) {
            String fName = convertJavaName(f.getName());
            list.add("ret.set" + fName + "(modelDo.get" + fName + "());");

        }
        list.add("return ret;");
        list.add("}");
        list.add("");
        list.add(
            "public static List<" + modelName + " > convertList(List<" + doName + " > doList) {");
        list.add("if ((doList == null) || (doList.size() < 1)) {            return null;        }");
        list.add("List<" + modelName + " > list = new ArrayList<" + modelName + " >();");
        list.add(" for (" + doName + "  modelDo : doList) {          ");
        list.add("" + modelName + "  model = convert(modelDo);    list.add(model);   }   ");
        list.add("return list;}");

        list.add("public static PageList<" + modelName + "> convertPageList(PageList<" + doName
                 + "> doPageList) {");
        list.add("List<" + modelName + "> modelList = convertList(doPageList.getResultList());");
        list.add("PageList<" + modelName + "> pageList = new PageList<" + modelName + ">();");
        list.add(" pageList.setPageSize(doPageList.getPageSize());");
        list.add(" pageList.setPageNum(doPageList.getPageNum());");
        list.add(" pageList.setMaxPageNum(doPageList.getMaxPageNum());");

        list.add("pageList.setTotalCount(doPageList.getTotalCount());");
        list.add("pageList.setResultList(modelList);");
        list.add("return pageList;");
        list.add("}");
        return list;
    }

    private List<String> genMapperList(Table table) {

        String modelName = convertJavaName(table.getName());
        String doName = modelName + "Do";
        List<String> list = new ArrayList<String>();
        list.add("<resultMap id=\"RM\"      type=\"com.****.common.dal.pg.dbo." + doName + "\">");
        for (Field f : table.getFieldList()) {
            if (f.isPk()) {
                list.add("<id property=\"" + convertPropertyName(f.getName()) + "\" column=\""
                         + f.getName() + "\" />");
            } else {
                list.add("<result property=\"" + convertPropertyName(f.getName()) + "\" column=\""
                         + f.getName() + "\" />");
            }
        }
        list.add(" </resultMap>");

        List<String> fieldNameList = getFieldNameList(table);
        list.add(" <sql id=\"allColumns\">");
        for (int i = 0; i < fieldNameList.size(); i++) {
            if (i == fieldNameList.size() - 1) {
                list.add(fieldNameList.get(i));
            } else {
                list.add(fieldNameList.get(i) + ",");
            }
        }

        list.add("</sql>");

        List<String> pkList = getPkFieldNameList(table);
        if (pkList != null) {
            list.add("<select id=\"getById\" resultMap=\"RM\" parameterType=\"long\">");
            list.add(
                "select        <include refid=\"allColumns\" />        from " + table.getName());
            list.add(" where " + Joiner.on(",").join(getPkWhereList(table)) + "    limit 1");
        }
        list.add("</select>");
        list.add("");
        //add

        list.add(
            " <insert id=\"add\" parameterType=\"com.****.common.dal.pg.dbo." + doName + "\">");
        list.add("  <selectKey keyProperty=\"id\" resultType=\"int\" order=\"BEFORE\">");
        list.add("select           nextval('seq_" + table.getName() + "')");
        list.add("  </selectKey>");
        list.add(" insert into " + table.getName()
                 + " (        <include refid=\"allColumns\" />        ) ");
        list.add(" values        (");
        List<String> valueList = getAddValueList(table);
        for (int i = 0; i < valueList.size(); i++) {
            if (i == valueList.size() - 1) {
                list.add(valueList.get(i));
            } else {
                list.add(valueList.get(i) + ",");
            }

        }

        list.add("  )    </insert>");
        list.add("");

        //delete

        list.add("<delete id=\"deleteById\" parameterType=\"long\">");
        list.add(" delete from        " + table.getName() + " ");
        list.add(" where        id = #{id}    </delete>");
        list.add("");
        list.add("");
        list.add(
            "<update id=\"update\"  parameterType=\"com.****.common.dal.pg.dbo." + doName + "\">");
        list.add(" update " + table.getName() + " set");
        for (Field f : table.getFieldList()) {
            if (f.getName().equals("gmt_modify") || f.getName().equals("gmt_create")) {
                continue;
            }
            list.add("<if test=\"" + convertPropertyName(f.getName()) + " != null and "
                     + convertPropertyName(f.getName()) + " != ''\">");
            list.add(f.getName() + " = #{" + convertPropertyName(f.getName()) + "},");
            list.add("</if>");
        }
        list.add("gmt_modify=now() ");
        list.add("where id=#{id}");
        list.add("</update>");

        list.add("");
        list.add("");
        list.add("");

        return list;
    }

    List<String> getFieldNameList(Table table) {
        List<String> list = new ArrayList<String>();
        for (Field f : table.getFieldList()) {
            list.add(f.getName());
        }
        return list;
    }

    List<String> getPkFieldNameList(Table table) {
        List<String> list = new ArrayList<String>();
        for (Field f : table.getFieldList()) {
            if (f.isPk()) {
                list.add(f.getName());
            }
        }
        return list;
    }

    List<String> getPkWhereList(Table table) {
        List<String> list = new ArrayList<String>();
        for (Field f : table.getFieldList()) {
            if (f.isPk()) {
                list.add(f.getName() + "= #{" + convertPropertyName(f.getName()) + "} ");
            }
        }
        return list;
    }

    List<String> getAddValueList(Table table) {
        List<String> list = new ArrayList<String>();
        for (Field f : table.getFieldList()) {
            if (f.getName().equals("gmt_create") || f.getName().equals("gmt_modify")) {
                list.add("now() ");
            } else {
                list.add("#{" + convertPropertyName(f.getName()) + "} ");
            }
        }
        return list;
    }

}
